[id].vue 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303
  1. <template>
  2. <div class="sales--print-page">
  3. <div class="sales--print-container">
  4. <!-- 헤더 -->
  5. <div class="sales--print-header">
  6. <h1>아우디 공식딜러 고진모터스</h1>
  7. <div class="audi--logo"><img src="/img/audi_logo.png" /></div>
  8. </div>
  9. <!-- 메인 콘텐츠 -->
  10. <div class="sales--print-content">
  11. <!-- 사진 영역 -->
  12. <div class="sales--print-photo">
  13. <img
  14. v-if="staff?.photo_url"
  15. :src="getImageUrl(staff.photo_url)"
  16. :alt="staff.name"
  17. />
  18. <div v-else class="sales--print-photo-empty">사진없음</div>
  19. </div>
  20. <!-- 정보 영역 -->
  21. <div class="sales--print-info">
  22. <div class="sales--print-row">
  23. <div class="sales--print-label">전시장</div>
  24. <div class="sales--print-value">{{ getShowroomName(staff?.showroom) }}</div>
  25. </div>
  26. <div class="sales--print-row">
  27. <div class="sales--print-label">팀</div>
  28. <div class="sales--print-value">{{ getTeamName(staff?.team) }}</div>
  29. </div>
  30. <div class="sales--print-row">
  31. <div class="sales--print-label">이름</div>
  32. <div class="sales--print-value sales--print-name">{{ staff?.name }}</div>
  33. </div>
  34. <div class="sales--print-row">
  35. <div class="sales--print-label">직책</div>
  36. <div class="sales--print-value">{{ getPositionName(staff?.position) }}</div>
  37. </div>
  38. <!-- <div class="sales--print-row">
  39. <div class="sales--print-label">대표번호</div>
  40. <div class="sales--print-value">{{ staff?.main_phone }}</div>
  41. </div> -->
  42. <div class="sales--print-row">
  43. <div class="sales--print-label">핸드폰</div>
  44. <div class="sales--print-value">{{ staff?.direct_phone }}</div>
  45. </div>
  46. <div class="sales--print-row">
  47. <div class="sales--print-label">이메일</div>
  48. <div class="sales--print-value">{{ staff?.email }}</div>
  49. </div>
  50. </div>
  51. </div>
  52. <!-- 프린트 버튼 (프린트 시 숨김) -->
  53. <div class="sales--print-actions no-print">
  54. <button class="sales--print-btn" @click="handlePrint">프린트</button>
  55. <button class="sales--print-btn sales--print-btn-secondary" @click="handleClose">
  56. 닫기
  57. </button>
  58. </div>
  59. </div>
  60. </div>
  61. </template>
  62. <script setup>
  63. import { ref, onMounted } from "vue";
  64. import { useRoute, useRouter } from "vue-router";
  65. definePageMeta({
  66. layout: "blank",
  67. });
  68. const route = useRoute();
  69. const router = useRouter();
  70. const { get } = useApi();
  71. const { getImageUrl } = useImage();
  72. const staff = ref(null);
  73. const showrooms = ref([]);
  74. // 데이터 로드
  75. const loadData = async () => {
  76. const id = route.params.id;
  77. // 영업사원 정보
  78. const { data: staffData } = await get(`/staff/sales/${id}`);
  79. if (staffData?.success && staffData?.data) {
  80. staff.value = staffData.data;
  81. }
  82. // 전시장 리스트
  83. const { data: branchData } = await get("/branch/list", { per_page: 1000 });
  84. if (branchData?.success && branchData?.data) {
  85. showrooms.value = branchData.data.items || [];
  86. }
  87. };
  88. // 전시장 이름 가져오기
  89. const getShowroomName = (showroomId) => {
  90. const showroom = showrooms.value.find((s) => s.id === showroomId);
  91. return showroom ? showroom.name : "-";
  92. };
  93. // 팀 이름 가져오기
  94. const getTeamName = (teamId) => {
  95. if (teamId === 0 || teamId === "0") {
  96. return "마스터팀";
  97. }
  98. return teamId ? `${teamId}팀` : "-";
  99. };
  100. // 직책 이름 가져오기
  101. const getPositionName = (positionCode) => {
  102. const positions = {
  103. 10: "팀장",
  104. 15: "마스터",
  105. 20: "차장",
  106. 30: "과장",
  107. 40: "대리",
  108. 60: "사원",
  109. };
  110. return positions[positionCode] || "-";
  111. };
  112. // 프린트
  113. const handlePrint = () => {
  114. window.print();
  115. };
  116. // 닫기
  117. const handleClose = () => {
  118. window.close();
  119. };
  120. onMounted(() => {
  121. loadData();
  122. });
  123. </script>
  124. <style scoped>
  125. .audi--logo {
  126. img {
  127. max-height: 50px;
  128. }
  129. }
  130. .sales--print-page {
  131. min-height: 100vh;
  132. background: #f5f5f5;
  133. padding: 20px;
  134. }
  135. .sales--print-container {
  136. max-width: 800px;
  137. margin: 0 auto;
  138. background: white;
  139. padding: 40px;
  140. box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
  141. }
  142. .sales--print-header {
  143. text-align: center;
  144. margin-bottom: 40px;
  145. padding-bottom: 20px;
  146. border-bottom: 2px solid #333;
  147. display: flex;
  148. align-items: center;
  149. justify-content: space-between;
  150. }
  151. .sales--print-header h1 {
  152. font-size: 28px;
  153. font-weight: bold;
  154. color: #000;
  155. margin: 0;
  156. }
  157. .sales--print-content {
  158. display: flex;
  159. gap: 40px;
  160. margin-bottom: 40px;
  161. }
  162. .sales--print-photo {
  163. flex-shrink: 0;
  164. width: 200px;
  165. height: 300px;
  166. border: 1px solid #ddd;
  167. border-radius: 8px;
  168. overflow: hidden;
  169. display: flex;
  170. align-items: center;
  171. justify-content: center;
  172. background: #f9f9f9;
  173. }
  174. .sales--print-photo img {
  175. width: 100%;
  176. height: 100%;
  177. object-fit: cover;
  178. }
  179. .sales--print-photo-empty {
  180. color: #999;
  181. font-size: 14px;
  182. }
  183. .sales--print-info {
  184. flex: 1;
  185. display: flex;
  186. flex-direction: column;
  187. gap: 20px;
  188. }
  189. .sales--print-row {
  190. display: flex;
  191. align-items: center;
  192. padding-bottom: 12px;
  193. border-bottom: 1px solid #e0e0e0;
  194. }
  195. .sales--print-label {
  196. width: 120px;
  197. font-weight: bold;
  198. color: #333;
  199. font-size: 15px;
  200. }
  201. .sales--print-value {
  202. flex: 1;
  203. color: #555;
  204. font-size: 15px;
  205. }
  206. .sales--print-name {
  207. font-size: 18px;
  208. font-weight: bold;
  209. color: #000;
  210. }
  211. .sales--print-actions {
  212. display: flex;
  213. justify-content: center;
  214. gap: 12px;
  215. margin-top: 40px;
  216. }
  217. .sales--print-btn {
  218. padding: 12px 32px;
  219. font-size: 16px;
  220. font-weight: bold;
  221. border: none;
  222. border-radius: 4px;
  223. cursor: pointer;
  224. background: #000;
  225. color: white;
  226. transition: background 0.2s;
  227. }
  228. .sales--print-btn:hover {
  229. background: #333;
  230. }
  231. .sales--print-btn-secondary {
  232. background: #666;
  233. }
  234. .sales--print-btn-secondary:hover {
  235. background: #888;
  236. }
  237. /* 프린트 스타일 */
  238. @media print {
  239. .sales--print-page {
  240. background: white;
  241. padding: 0;
  242. }
  243. .sales--print-container {
  244. max-width: none;
  245. box-shadow: none;
  246. padding: 20px;
  247. }
  248. .no-print {
  249. display: none !important;
  250. }
  251. .sales--print-header {
  252. margin-bottom: 30px;
  253. }
  254. .sales--print-content {
  255. margin-bottom: 0;
  256. }
  257. }
  258. </style>